package org.gdstash.item;

public class GDRandomUniform {
    private static final int a = 16807;
    private static final int m = Integer.MAX_VALUE;
    private static final int q = 127773;
    private static final int r = 2836;
    private long previous;

    public GDRandomUniform(final int seed) {
        this.setSeed(seed);
    }

    private long generate() {
        final int hi = (int) (this.previous / 127773L);
        final int lo = (int) (this.previous - 127773 * hi);
        final int t = 16807 * lo - 2836 * hi;
        if (t >= 0) {
            this.previous = t;
        } else {
            this.previous = t + Integer.MAX_VALUE;
        }
        return this.previous;
    }

    public void setSeed(final int seed) {
        long l = 0L;
        if (seed < 0) {
            l = intToUnsignedLong(seed);
        } else {
            l = seed;
        }
        this.setSeedLong(l);
    }

    private void setSeedLong(final long seed) {
        this.previous = seed;
        this.generate();
    }

    public float generateFloat(final int min, final int max) {
        final float f = this.generate() / 2.14748365E9f;
        return f * (max - min) + min;
    }

    public int generateInt(final int min, final int max) {
        final long l = this.generate();
        return (int) (l % (max - min + 1)) + min;
    }

    public long generateSeed() {
        return this.generate();
    }

    public static long intToUnsignedLong(final int i) {
        return (long) i & 0xFFFFFFFFL;
    }
}
